/*
 * commons is a based project implemented
 * Copyright (C) 2024 Jasmine
 */
package com.commons.log.http;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import com.commons.core.constant.StringPool;
import com.commons.ip.utils.IpUtil;
import com.commons.log.domain.RecordableHttpRequest;

import jakarta.servlet.http.HttpServletRequest;

/**
 * 可记录的 HTTP 请求信息适配器
 */
public final class RecordableServletHttpRequest implements RecordableHttpRequest {

    private final HttpServletRequest request;

    public RecordableServletHttpRequest(HttpServletRequest request) {
        this.request = request;
    }

    @Override
    public String getMethod() {
        return request.getMethod();
    }

    @Override
    public URI getUrl() {
        String queryString = request.getQueryString();
        if (StringUtils.isBlank(queryString)) {
            return URI.create(request.getRequestURL().toString());
        }
        try {
            StringBuilder urlBuilder = this.appendQueryString(queryString);
            return new URI(urlBuilder.toString());
        } catch (URISyntaxException e) {
            String encoded = UriUtils.encodeQuery(queryString, StandardCharsets.UTF_8);
            StringBuilder urlBuilder = this.appendQueryString(encoded);
            return URI.create(urlBuilder.toString());
        }
    }

    @Override
    public String getIp() {
        return IpUtil.getRemoteIP(request);
    }

    @Override
    public Map<String, String> getHeaders() {
        Map<String, String> headerMap = new HashMap();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headerMap.put(headerName, request.getHeader(headerName));
        }
        return headerMap;
    }

    @Override
    public String getParams() {
        ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
        if (null != wrapper) {
            return StringUtils.toEncodedString(wrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
        }

        return null;
    }

    private StringBuilder appendQueryString(String queryString) {
        return new StringBuilder().append(request.getRequestURL()).append(StringPool.QUESTION_MARK).append(queryString);
    }
}